home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / mac / files / infodata / callbook.tar / callbook_1.3 / telnet.c < prev    next >
C/C++ Source or Header  |  1991-08-27  |  9KB  |  666 lines

  1. /*
  2.  * Telnet callsign server sources copyright 1989 by Devon Bowen, KA2NRC.
  3.  * You may distribute and modify these files as you please as long as
  4.  * as long as credit to the original creator is given. Please report any
  5.  * bug fixes or modification to bowen@cs.buffalo.edu.
  6.  */
  7.  
  8. #include <syslog.h>
  9. #include <stdio.h>
  10. #include <arpa/telnet.h>
  11.  
  12. int curr_row=0;
  13. int max_row=23;
  14.  
  15. int in_echo=0, in_sga=0;        /* only two options supported */
  16.  
  17. unsigned char readchar();
  18.  
  19. tinit()
  20. {
  21.     unsigned char request[6], ch;
  22.  
  23.     in_echo = in_sga = 1;
  24.  
  25.     request[0] = IAC;
  26.     request[1] = WILL;
  27.     request[2] = TELOPT_ECHO;
  28.     request[3] = IAC;
  29.     request[4] = WILL;
  30.     request[5] = TELOPT_SGA;
  31.  
  32.     if (write(1, request, 6) == -1) {
  33.         syslog(LOG_ERR, "%m");
  34.         exit(1);
  35.     }
  36.  
  37.     while (in_echo == 1 || in_sga == 1) {
  38.         ch = readchar();
  39.         check_state(&ch);
  40.     }
  41. }
  42.  
  43.  
  44. will(option)
  45. int option;
  46. {
  47.     unsigned char request[3], ch;
  48.     int *watch;
  49.  
  50.     switch (option) {
  51.         case TELOPT_ECHO : if (in_echo == 2) return(0);
  52.  
  53.                    watch = &in_echo;
  54.                    in_echo = 1;
  55.  
  56.                    break;
  57.  
  58.         case TELOPT_SGA  : if (in_sga == 2) return(0);
  59.  
  60.                    watch = &in_sga;
  61.                    in_sga = 1;
  62.  
  63.                    break;
  64.     }
  65.  
  66.     request[0] = IAC;
  67.     request[1] = WILL;
  68.     request[2] = option;
  69.  
  70.     if (write(1, request, 3) == -1) {
  71.         syslog(LOG_ERR, "%m");
  72.         exit(1);
  73.     }
  74.  
  75.     while (*watch == 1) {
  76.         ch = readchar();
  77.         check_state(&ch);
  78.     }
  79. }
  80.  
  81.  
  82. char
  83. tgetchar()
  84. {
  85.     char ch;
  86.     static char nextchar = 0;
  87.  
  88.     if (nextchar) {
  89.         ch = nextchar;
  90.         nextchar = 0;
  91.  
  92.     } else {
  93.         ch = readchar();
  94.  
  95.         while (!check_state(&ch) || ch == '\0')
  96.             ch = readchar();
  97.     }
  98.  
  99.     if (ch == '\n')
  100.         if ((ch = readchar()) == '\r')
  101.             return('\n');
  102.         else {
  103.             nextchar = ch;
  104.             return('\n');
  105.         }
  106.  
  107.     if (ch == '\r')
  108.         if ((ch = readchar()) == '\n')
  109.             return('\n');
  110.         else {
  111.             nextchar = ch;
  112.             return('\n');
  113.         }
  114.  
  115.     return(ch);
  116. }
  117.  
  118.  
  119. char *
  120. tgets(buf, size)
  121. char *buf;
  122. int size;
  123. {
  124.     int cnt = 0 ;
  125.     char *ind = buf, ch = 'a';
  126.  
  127.     curr_row = 0;
  128.  
  129.     while (ch != '\0') {
  130.  
  131.         switch (ch = tgetchar()) {
  132.  
  133.             case '\177' :   /* delete */
  134.             case '\010' :   /* control h */
  135.  
  136.                 if (!in_sga) {
  137.  
  138.                     if (cnt <= size) {
  139.  
  140.                         if (in_echo && cnt < size)
  141.                             echo(ch);
  142.  
  143.                         *ind = ch;
  144.                         ind++;
  145.                         cnt++;
  146.                     }
  147.  
  148.                     break;
  149.                 }
  150.  
  151.                 if (cnt != 0) {
  152.  
  153.                     if (*(ind-1) < 040)
  154.                         send_ec(2);
  155.                     else
  156.                         send_ec(1);
  157.  
  158.                     cnt--;
  159.                     ind--;
  160.                 }
  161.  
  162.                 break;
  163.  
  164.             case '\025' :    /* control u */
  165.             case '\030' :   /* control x */
  166.  
  167.                 if (!in_sga) {
  168.  
  169.                     if (cnt <= size) {
  170.  
  171.                         if (in_echo && cnt < size)
  172.                             echo(ch);
  173.  
  174.                         *ind = ch;
  175.                         ind++;
  176.                         cnt++;
  177.                     }
  178.  
  179.                     break;
  180.                 }
  181.  
  182.                 if (cnt != 0)
  183.                     for (; cnt > 0; cnt--) {
  184.                         if (*(ind-1) < 040)
  185.                             send_ec(2);
  186.                         else
  187.                             send_ec(1);
  188.  
  189.                         ind--;
  190.                     }
  191.  
  192.                 break;
  193.  
  194.             case '\027' :   /* control w */
  195.  
  196.                 if (!in_sga) {
  197.  
  198.                     if (cnt <= size) {
  199.  
  200.                         if (in_echo && cnt < size)
  201.                             echo(ch);
  202.  
  203.                         *ind = ch;
  204.                         ind++;
  205.                         cnt++;
  206.                     }
  207.  
  208.                     break;
  209.                 }
  210.  
  211.                 if (cnt != 0) {
  212.  
  213.                     while (*(ind-1) == ' ' && cnt > 0) {
  214.                         if (*(ind-1) < 040)
  215.                             send_ec(2);
  216.                         else
  217.                             send_ec(1);
  218.  
  219.                         cnt--;
  220.                         ind--;
  221.                     }
  222.  
  223.                     while (*(ind-1) != ' ' && cnt > 0) {
  224.                         if (*(ind-1) < 040)
  225.                             send_ec(2);
  226.                         else
  227.                             send_ec(1);
  228.  
  229.                         cnt--;
  230.                         ind--;
  231.                     }
  232.                 }
  233.  
  234.                 break;
  235.  
  236.             case '\n' :
  237.  
  238.                 if (in_echo)
  239.                     echo(ch);
  240.  
  241.                 if (cnt <= size) {
  242.  
  243.                     *ind = '\0';
  244.                     return(buf);
  245.  
  246.                 } else
  247.                     return(NULL);
  248.  
  249.             default :
  250.  
  251.                 if (in_echo)
  252.                     echo(ch);
  253.  
  254.                 if (cnt <= size) {
  255.                     *ind = ch;
  256.                     ind++;
  257.                     cnt++;
  258.                 }
  259.  
  260.                 break;
  261.         }
  262.     }
  263. }
  264.  
  265.  
  266. tputs(str, send_ga)
  267. char *str;
  268. {
  269.     char buffer[BUFSIZ];
  270.     int bufcnt=0, limit;
  271.     static int curr_col=0;
  272.  
  273.     limit = BUFSIZ - 10;
  274.  
  275.     for (; *str; str++) {
  276.  
  277.         if (*str == '\n') {
  278.  
  279.             buffer[bufcnt++] = '\r';
  280.             buffer[bufcnt++] = '\n';
  281.             curr_row++;
  282.             curr_col = 0;
  283.  
  284.             if (max_row && curr_row == max_row) {
  285.  
  286.                 if (write(1, buffer, bufcnt) == -1) {
  287.                     syslog(LOG_ERR, "%m");
  288.                     exit(1);
  289.                 }
  290.  
  291.                 bufcnt = 0;
  292.                 curr_col = 0;
  293.  
  294.                 if (write(1, "-- more --", 10) == -1) {
  295.                     syslog(LOG_ERR, "%m");
  296.                     exit(1);
  297.                 }
  298.  
  299.                 switch (tgetchar()) {
  300.  
  301.                     case 'q'  :
  302.                         curr_row = 0;
  303.                         send_ec(10);
  304.                         return 1;
  305.  
  306.                     case ' '  :
  307.                         curr_row = 0;
  308.                         break;
  309.  
  310.                     default     :
  311.                         curr_row--;
  312.                         break;
  313.                 }
  314.  
  315.                 send_ec(10);
  316.             }
  317.                 
  318.  
  319.         } else if (*str < 040) {
  320.  
  321.             buffer[bufcnt++] = '^';
  322.             buffer[bufcnt++] = *str + 0100;
  323.             curr_col += 2;
  324.  
  325.         } else {
  326.  
  327.             buffer[bufcnt++] = *str;
  328.             curr_col++;
  329.  
  330.             if (curr_col == 80) {
  331.                 curr_col = 0;
  332.                 curr_row++;
  333.             }
  334.  
  335.             if (max_row && curr_row == max_row) {
  336.  
  337.                 if (write(1, buffer, bufcnt) == -1) {
  338.                     syslog(LOG_ERR, "%m");
  339.                     exit(1);
  340.                 }
  341.  
  342.                 bufcnt = 0;
  343.                 curr_col = 0;
  344.  
  345.                 if (write(1, "-- more --", 10) == -1) {
  346.                     syslog(LOG_ERR, "%m");
  347.                     exit(1);
  348.                 }
  349.  
  350.                 switch (tgetchar()) {
  351.  
  352.                     case 'q'  :
  353.                         curr_row = 0;
  354.                         send_ec(10);
  355.                         return 1;
  356.  
  357.                     case ' '  :
  358.                         curr_row = 0;
  359.                         break;
  360.  
  361.                     default     :
  362.                         curr_row--;
  363.                         break;
  364.                 }
  365.  
  366.                 send_ec(10);
  367.             }
  368.         }
  369.  
  370.         if (bufcnt > limit) {
  371.  
  372.             if (write(1, buffer, bufcnt) == -1) {
  373.                 syslog(LOG_ERR, "%m");
  374.                 exit(1);
  375.             }
  376.  
  377.             bufcnt = 0;
  378.         }
  379.  
  380.     }
  381.  
  382.     if (bufcnt != 0)
  383.  
  384.         if (write(1, buffer, bufcnt) == -1) {
  385.             syslog(LOG_ERR, "%m");
  386.             exit(1);
  387.         }
  388.  
  389.     if (send_ga && !in_sga) {
  390.  
  391.         buffer[0] = IAC;
  392.         buffer[1] = GA;
  393.  
  394.         if (write(1, buffer, 2) == -1) {
  395.             syslog(LOG_ERR, "%m");
  396.             exit(1);
  397.         }
  398.     }
  399.  
  400.     return 0;
  401. }
  402.  
  403.  
  404. #define NORMAL   1
  405. #define GOT_IAC  2
  406. #define GOT_DO   3
  407. #define GOT_DONT 4
  408. #define GOT_WILL 5
  409. #define GOT_WONT 6
  410.  
  411. check_state(next)
  412. unsigned char *next;
  413. {
  414.     static int state = NORMAL;
  415.  
  416.     switch (state) {
  417.  
  418.         case NORMAL   : if (*next == IAC) {
  419.                     state = GOT_IAC;
  420.                     return(0);
  421.                 }
  422.  
  423.                 return(1);
  424.  
  425.         case GOT_IAC  : switch (*next) {
  426.                     case DO :
  427.  
  428.                         state = GOT_DO;
  429.                         return(0);
  430.  
  431.                     case DONT :
  432.  
  433.                         state = GOT_DONT;
  434.                         return(0);
  435.  
  436.                     case WILL :
  437.  
  438.                         state = GOT_WILL;
  439.                         return(0);
  440.  
  441.                     case WONT :
  442.  
  443.                         state = GOT_WONT;
  444.                         return(0);
  445.  
  446.                     case IAC :
  447.  
  448.                         state = NORMAL;
  449.                         return(1);
  450.  
  451.                     case EC :
  452.  
  453.                         state = NORMAL;
  454.                         *next = '\010';
  455.                         return(1);
  456.  
  457.                     case EL :
  458.  
  459.                         state = NORMAL;
  460.                         *next = '\025';
  461.                         return(1);
  462.  
  463.                     default :
  464.  
  465.                         state = NORMAL;
  466.                         return(0);
  467.                 }
  468.  
  469.         case GOT_DO   : switch (*next) {
  470.  
  471.                     case TELOPT_ECHO :
  472.  
  473.                         if (in_echo != 1)
  474.                             ack_will(*next);
  475.  
  476.                         in_echo = 2;
  477.  
  478.                         break;
  479.  
  480.                     case TELOPT_SGA :
  481.  
  482.                         if (in_sga != 1)
  483.                             ack_will(*next);
  484.  
  485.                         in_sga = 2;
  486.  
  487.                         break;
  488.  
  489.                     default :
  490.  
  491.                         ack_wont(*next);
  492.                         break;
  493.                 }
  494.  
  495.                 state = NORMAL;
  496.                 return(0);
  497.  
  498.         case GOT_DONT : switch (*next) {
  499.  
  500.                     case TELOPT_ECHO :
  501.  
  502.                         if (in_echo == 1)
  503.                             in_echo = 0;
  504.                         else {
  505.                             in_echo = 0;
  506.                             ack_wont(*next);
  507.                         }
  508.  
  509.                         break;
  510.  
  511.                     case TELOPT_SGA :
  512.  
  513.                         if (in_sga == 1)
  514.                             in_sga = 0;
  515.                         else {
  516.                             in_sga = 0;
  517.                             ack_wont(*next);
  518.                         }
  519.  
  520.                         break;
  521.                 }
  522.  
  523.                 state = NORMAL;
  524.                 return(0);
  525.  
  526.         case GOT_WILL : ack_dont(*next);
  527.                 state = NORMAL;
  528.                 return(0);
  529.  
  530.         case GOT_WONT : state = NORMAL;
  531.                 return(0);
  532.     }
  533. }
  534.  
  535.  
  536. unsigned char
  537. readchar()
  538. {
  539.     static int cc = 0;
  540.     static unsigned char *ind, buf[BUFSIZ];
  541.  
  542.     if (!cc) {
  543.  
  544.         switch (cc = read(0, buf, BUFSIZ-1)) {
  545.             case -1 : syslog(LOG_ERR, "%m");
  546.                   exit(1);
  547.             case  0 : syslog(LOG_ERR, "socket closed");
  548.                   exit(1);
  549.         }
  550.  
  551.         ind = buf;
  552.  
  553.     } else
  554.  
  555.         ind++;
  556.  
  557.     cc--;
  558.     return(*ind);
  559. }
  560.  
  561.  
  562. ack_will(option)
  563. unsigned char option;
  564. {
  565.     unsigned char request[3];
  566.  
  567.     request[0] = IAC;
  568.     request[1] = WILL;
  569.     request[2] = option;
  570.  
  571.     if (write(1, request, 3) == -1) {
  572.         syslog(LOG_ERR, "%m");
  573.         exit(1);
  574.     }
  575. }
  576.  
  577.  
  578. ack_wont(option)
  579. unsigned char option;
  580. {
  581.     unsigned char request[3];
  582.  
  583.     request[0] = IAC;
  584.     request[1] = WONT;
  585.     request[2] = option;
  586.  
  587.     if (write(1, request, 3) == -1) {
  588.         syslog(LOG_ERR, "%m");
  589.         exit(1);
  590.     }
  591. }
  592.  
  593.  
  594. ack_dont(option)
  595. unsigned char option;
  596. {
  597.     unsigned char request[3];
  598.  
  599.     request[0] = IAC;
  600.     request[1] = DONT;
  601.     request[2] = option;
  602.  
  603.     if (write(1, request, 3) == -1) {
  604.         syslog(LOG_ERR, "%m");
  605.         exit(1);
  606.     }
  607. }
  608.  
  609.  
  610. echo(what)
  611. char what;
  612. {
  613.     char temp[2];
  614.  
  615.     if (what == '\n') {
  616.  
  617.         temp[0] = '\r';
  618.         temp[1] = '\n';
  619.  
  620.         if (write(1, temp, 2) == -1) {
  621.             syslog(LOG_ERR, "%m");
  622.             exit(1);
  623.         }
  624.  
  625.     } else if (what < 040) {
  626.  
  627.         temp[0] = '^';
  628.         temp[1] = what + 0100;
  629.  
  630.         if (write(1, temp, 2) == -1) {
  631.             syslog(LOG_ERR, "%m");
  632.             exit(1);
  633.         }
  634.  
  635.     } else {
  636.  
  637.         temp[0] = what;
  638.  
  639.         if (write(1, temp, 1) == -1) {
  640.             syslog(LOG_ERR, "%m");
  641.             exit(1);
  642.         }
  643.     }
  644. }
  645.  
  646.  
  647. send_ec(count)
  648. int count;
  649. {
  650.     int i;
  651.     char temp[BUFSIZ];
  652.  
  653.     count *= 3;
  654.  
  655.     for (i=0; i < count; i+=3) {
  656.         temp[i] = '\010';
  657.         temp[i+1] = '\040';
  658.         temp[i+2] = '\010';
  659.     }
  660.  
  661.     if (write(1, temp, count) == -1) {
  662.         syslog(LOG_ERR, "%m");
  663.         exit(1);
  664.     }
  665. }
  666.